package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.Exception.LyException;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_UP_KEY;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    AmqpTemplate amqpTemplate;
    @Autowired
    CategoryService categoryService;
    @Autowired
    BrandService brandService;
    @Autowired
   SpuDetailService detailService;
    @Autowired
    SkuService skuService;
    @Autowired
    SpecParamService paramService;
    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        // 1.健壮性
        int current = Math.max(page, 1);
        int size = Math.max(rows, 5);

        // 2.准备查询条件
        Page<Spu> result = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                // 3.准备分页条件 LIMIT ?, ?
                .page(new Page<>(current, size));

        // 4.解析查询结果
        long total = result.getTotal();
        long pages = result.getPages();
        List<Spu> list = result.getRecords();

        // 5.转换DTO
        List<SpuDTO> dtoList = SpuDTO.convertEntityList(list);
        for (SpuDTO spuDTO : dtoList) {
            // 查询spu的分类和品牌的名称
            handleCategoryAndBrandName(spuDTO);
        }

        // 6.封装分页结果并返回
        return new PageDTO<>(total, pages, dtoList);
    }

    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        // 根据品牌id查询品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if(brand != null) {
            spuDTO.setBrandName(brand.getName());
        }
        // 根据三级分类id查询分类集合
        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if(!CollectionUtils.isEmpty(categories)) {
            // 取出分类的名称，拼接起来
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }
    @Override
    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
    //1.新增Spu
        //1.1转换DTO为PO
        Spu spu = spuDTO.toEntity(Spu.class);
        //1.2.默认下架
        spu.setSaleable(false);
       //1.3.保存商品
        boolean success = save(spu);
        if (!success){
            throw  new LyException("新增商品失败",500);
        }
        //1.4.获取回显的id
        Long spuId= spu.getId();
        //2.新增SpuDetail 转换DTO为PO
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        //2.1填写id
        spuDetail.setSpuId(spuId);
        //2.2.写入数据库
        success = detailService.save(spuDetail);
        if (!success){
            throw  new LyException("新增商品详情失败",500);
        }
        // 4.新增Sku
        List<SkuDTO> spuDTOSkus = spuDTO.getSkus();
        //4.1转换DTO为PO
        ArrayList<Sku> skus = new ArrayList<>(spuDTOSkus.size());
        for (SkuDTO dtoSkus : spuDTOSkus) {

            Sku sku = dtoSkus.toEntity(Sku.class);
            skus.add(sku);
            //填充字段
            sku.setSaleable(false);
            sku.setSpuId(spuId);
            sku.setSold(0L);

        }


      /*  List<Sku> list = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());*/
        // 批量新增
        skuService.saveBatch(skus);
    }

    @Override
    @Transactional //多张表的更新需开启事物
    public void updateSaleable(Long id, boolean saleable) {
        //更新spu上下架
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean succes = updateById(spu);
        if (!succes){
            throw new LyException("更新失败",500);
        }
        //更新sku
        succes=skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!succes){
            throw new LyException("更新失败",500);
        }
        //发送消息
        String routingKey=saleable ? ITEM_UP_KEY : ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(ITEM_EXCHANGE_NAME,routingKey,id);
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        //1.0 查询spu
        Spu spu = getById(id);
        //1.1 判断
        if (spu==null){
            throw  new LyException("查询失败,商品id不存在",400);
        }
       //1.2转化成DTO
        SpuDTO spuDTO = new SpuDTO(spu);
        //2.0 查询SpuDetail
        SpuDetail spuDetail = detailService.getById(id);
        //2.1判断
        if (spuDetail==null){
            throw  new LyException("查询失败,商品id不存在",400);
        }
        //2.2 转化成DTO
        SpuDetailDTO spuDetailDTO = new SpuDetailDTO(spuDetail);
        spuDTO.setSpuDetail(spuDetailDTO);
        //3 查询 sku
        List<Sku> list = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(list)){
            throw new LyException("查询失败,商品id不存在",400);
        }
        //3.1 转为DTO
        List<SkuDTO> skuDTOS= SkuDTO.convertEntityList(list);
        spuDTO.setSkus(skuDTOS);
        //4. 准备商品分类和品牌名称
        handleCategoryAndBrandName(spuDTO);
        return spuDTO;
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
     //1.判断参数中是否包含spu的Id
        Long spuId = spuDTO.getId();
        if (spuId !=null){
            //1.1 说明spu有变化,需要修改,转为Po
            Spu spu = spuDTO.toEntity(Spu.class);
            //1.2确保不更新saleable
            spu.setSaleable(null);
            //1.3更新
            boolean success = updateById(spu);
            if (!success){
                throw  new LyException("更新商品失败",500);
            }
        }
        //2.判断是否包含spuDetail
        SpuDetailDTO detailDTO = spuDTO.getSpuDetail();
        if (detailDTO!=null && detailDTO.getSpuId()!=null){
            //2.1修改spuDetail,转为Po
            SpuDetail detail = detailDTO.toEntity(SpuDetail.class);
            //2.2更新
            boolean success = detailService.updateById(detail);
            if (!success){
                throw  new LyException("商品更新失败",500);
            }

        }
        //3.判断是否包含sku
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skuDTOList)){
            //不包含sku就不需要修改
          return;
        }
        //4.把DTO转PO
        Map<Boolean, List<Sku>> skuMap = skuDTOList.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                //5.判断是否包含saleable
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() != null));
        //6.包含saleable: 需要删除的sku
        List<Sku> deleteSkuList = skuMap.get(true);
        //6.1判断是否为空
        if (!CollectionUtils.isEmpty(deleteSkuList)){
            //6.2 不为空,获取待删除的sku的id集合
            List<Long> deleteIdList = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
            //6.3批量删除
            skuService.removeByIds(deleteIdList);
        }
        //7.不包含saleable 需要新增或修改的sku
        List<Sku> saveOrUpdateSkuList = skuMap.get(false);
        //7.1判断是否为空
        if (!CollectionUtils.isEmpty(saveOrUpdateSkuList)){
            //7.2不为空,需要增或改
            skuService.saveOrUpdateBatch(saveOrUpdateSkuList);
        }

    }

    @Override
    public List<SpecParamDTO> querySpecValue(Long id, Boolean searching) {
        //1.查询spu
        Spu spu = getById(id);
        //2.获取分类信息
        Long categoryId = spu.getCid3();
        //3.根据分类查询规格参数key
        List<SpecParamDTO> params = paramService.queryParams(categoryId, null, searching);
        //4.查询规格参数的值
        SpuDetail detail = detailService.getById(id);
        //4.1 获取规格参数值
        String specification = detail.getSpecification();
        //4.2 把json转为Map,key是param的id value是param 的值
        Map<Long, Object> valueMap = JsonUtils.toMap(specification, Long.class, Object.class);
        //5 遍历 给每个param找到对应的value
        for (SpecParamDTO param : params) {
            Long  keyId = param.getId();
            Object value = valueMap.get(keyId);
            param.setValue(value);
        }
        return params;
    }

}

